<template>
  <div class="mod-resource">
    <el-container>
      <el-aside style="width: 35%; min-width: 400px">
        <el-card class="box-card">
          <template #header>
            <div class="clearfix">
              <span class="r-title">菜单目录</span>
            </div>
          </template>
          <div class="toolbar-box">
            <el-row :gutter="20">
              <el-col :span="11">
                <el-input placeholder="输入关键字进行过滤" v-model="filterTreeText" />
              </el-col>
              <el-col :span="13">
                <el-button-group class="toolbar-btngroup fr">
                  <el-button v-if="admin.isAuth('admin:resource:save')" @click="() => addMenuEvent('add-root')" type="primary"> 新增 </el-button>
                  <el-button v-if="admin.isAuth('admin:resource:save')" @click="() => updateMenuEvent()" type="warning"> 修改 </el-button>
                  <el-button v-if="admin.isAuth('admin:resource:delete')" @click="() => deleteMenuEvent()" type="danger"> 删除 </el-button>
                </el-button-group>
              </el-col>
            </el-row>
          </div>
          <div style="height: 410px;">
            <el-scrollbar style="height: 100%">
              <el-tree
                node-key="id"
                class="filter-tree"
                :props="menu.props"
                :data="menu.data"
                default-expand-all
                highlight-current
                empty-text="木有数据~"
                :expand-on-click-node="false"
                v-loading.lock="menu.loading"
                element-loading-text="拼命加载中"
                :default-expanded-keys="menu.expandedKeys"
                @node-expand="menuNodeExpandEvent"
                @node-collapse="menuNodeCollapseEvent"
                :filter-node-method="filterTreeNode"
                ref="treeRef"
              >
                <template #default="{ node, data }">
                  <span class="custom-tree-node">
                    <icon-svg v-if="data.attributes && data.attributes.icon" :name="data.attributes.icon"></icon-svg>
                    <span>{{ node.label }}&nbsp;&nbsp;</span>
                    <span class="fr">
                      <el-button v-if="admin.isAuth('admin:resource:save')" size="small" type="primary" link @click="() => addMenuEvent('add-node', data)">
                        新增
                      </el-button>
                      <el-button v-if="admin.isAuth('admin:resource:list')" size="small" type="info" link @click="() => loadRequestEvent(node, data)">
                        资源
                      </el-button>
                    </span>
                  </span>
                </template>
              </el-tree>
            </el-scrollbar>
          </div>
        </el-card>
      </el-aside>
      <el-main v-if="table.show" style="padding: 0 20px">
        <el-card class="box-card">
          <template #header>
            <div class="clearfix">
              <span class="r-title">菜单[{{ (menu.selectData && menu.selectData.name) || "" }}] - 资源管理</span>
            </div>
          </template>
          <data-table ref="dataTableRef" name="resource" :initLoad="true" :pagination="false" :url="table.url">
            <!-- ------------------------------------------ 工具栏 ------------------------------------------ -->
            <template v-slot:toolbar>
              <el-button-group>
                <el-button v-if="admin.isAuth('admin:resource:save')" @click="() => addRequestEvent('add-node')" type="primary">
                  新增
                </el-button>
                <el-button v-if="admin.isAuth('admin:resource:save')" @click="() => updateRequestEvent()" type="warning">
                  修改
                </el-button>
                <el-button v-if="admin.isAuth('admin:resource:delete')" @click="() => deleteRequestEvent()" type="danger">
                  删除
                </el-button>
              </el-button-group>
            </template>
            <!-- ---------------------------------------- 数据表格列 ---------------------------------------- -->
            <el-table-column fixed prop="code" show-overflow-tooltip header-align="center" align="left" label="请求代码" width="220" />
            <el-table-column prop="name" show-overflow-tooltip header-align="center" align="left" width="180" label="请求名称" />
            <el-table-column prop="url" show-overflow-tooltip header-align="center" align="left" label="请求地址" width="260" />
            <el-table-column prop="description" show-overflow-tooltip header-align="center" align="left" width="220" label="描述" />
          </data-table>
        </el-card>
      </el-main>
    </el-container>
    <!-- 弹窗, 新增 / 修改 -->
    <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdateRef" @initMenuData="initMenuData" @initRequestData="loadTableData"></add-or-update>
  </div>
</template>

<script lang="ts" setup>
import admin from "@/utils/admin";
import http from "@/utils/httpRequest";
import { ref, nextTick, reactive, watch, onMounted } from "vue";
import { ElTree, ElMessage, ElMessageBox } from "element-plus";

import AddOrUpdate from './resource-add-or-update.vue';

// 菜单相关属性
const menu = reactive({
  // 属性结构
  data: [],
  // 加载状态
  loading: false,
  // 当前选中的节点，即当前查看请求列表的菜单节点
  selectData: undefined,
  // 菜单树默认属性
  props: {
    label: 'name',
    children: 'children'
  },
  expandedKeys: []
});

// 请求列表相关属性
const table = reactive({
  // 是否显示菜单请求列表
  show: false,
  // 请求列表加载状态
  url: ''
});

// 菜单树过滤文本
const filterTreeText = ref('');

// 新增修改弹窗是否显示
const addOrUpdateVisible = ref(false);

// 数据表格引用
const dataTableRef = ref();

// 弹窗引用
const addOrUpdateRef = ref();

// 资源树引用
const treeRef = ref<InstanceType<typeof ElTree>>();

// 监听查询内容变化
watch(filterTreeText, (n, o) => {
  treeRef.value!.filter(n);
});

// 组件挂载完成后执行
onMounted(() => {
  // 左侧加载菜单
  initMenuData();
});

// 左侧加载菜单
const initMenuData = () => {
  menu.loading = true;
  http
    .get({
      url: '/resource/tree',
    })
    .then(({ data }) => {
      if (http.success(data) && data.body) {
        menu.data = data.body;
      }
      menu.loading = false;
    });
};

// 新增菜单
const addMenuEvent = async (action, data = null) => {
  addOrUpdateVisible.value = true;
  await nextTick();
  addOrUpdateRef.value.initForm(action, 'menu', action === 'add-root' ? menu.data : data);
};

// 修改菜单
const updateMenuEvent = async () => {
  let node = treeRef.value.getCurrentNode()
  if (!node) {
    ElMessage.error('请先选择要修改的菜单！');
    return
  }
  addOrUpdateVisible.value = true;
  await nextTick();
  addOrUpdateRef.value.initForm('update-node', 'menu', node);
};

// 新增请求
const addRequestEvent = async (action, data = null) => {
  addOrUpdateVisible.value = true;
  await nextTick();
  addOrUpdateRef.value.initForm(action, 'request', action === 'add-node' ? menu.selectData : data);
};

// 修改请求
const updateRequestEvent = async () => {
  // 验证并获取是否选择一条数据
  let data = admin.obtainOneSelectionTableData(dataTableRef.value)
  if (!data) {
    return;
  }
  addOrUpdateVisible.value = true;
  await nextTick();
  addOrUpdateRef.value.initForm('update-node', 'request', data);
};

// 查看菜单下请求列表
const loadRequestEvent = async (node, data) => {
  menu.selectData = data;
  table.url = `/resource/list?pid=${data.id}`;
  table.show = true;
  await nextTick();
  loadTableData();
};

// 删除菜单
const deleteMenuEvent = () => {
  let node = treeRef.value.getCurrentNode();
  if (!node) {
    ElMessage.error('请先选择要删除的菜单！');
    return;
  }
  deleteResourceData(node, 'menu');
};

// 删除请求事件
const deleteRequestEvent = () => {
  let datas = dataTableRef.value.getSelection();
  if (!datas || datas.length <= 0) {
    ElMessage.error('请先选择要删除的请求！');
    return;
  }
  deleteResourceData(datas, 'request');
};

// 删除资源信息
const deleteResourceData = (data, type) => {
  let msg;
  let deleteIds = [];
  if (Array.isArray(data)) {
    msg = `确定要删除选中的[${data.length}]条${type === 'menu' ? '菜单' : '请求'}记录吗?`;
    for (let i = 0; i < data.length; i++) {
      deleteIds.push(data[i].id);
    }
  } else {
    msg = `确定要删除[${data.name}]${type === 'menu' ? '菜单' : '请求'}吗?`;
    deleteIds.push(data.id);
  }
  ElMessageBox
    .confirm(msg, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    .then(() => {
      http
        .instance({
          url: http.adornUrl('/resource/delete'),
          method: "post",
          data: http.adornData(deleteIds, false),
        })
        .then(({ data }) => {
          if (http.success(data, true, true)) {
            type === 'menu' ? initMenuData() : loadTableData();
          }
        })
        .catch(err => {
          console.error(err);
        });
    })
    .catch(()=>{});
};

// 菜单展开事件
const menuNodeExpandEvent = (data) => {
  if (menu.expandedKeys.indexOf(data.id) === -1) {
    menu.expandedKeys.push(data.id);
  }
};

// 菜单关闭事件
const menuNodeCollapseEvent = (data) => {
  let expandedKeys = menu.expandedKeys;
  for (let i = 0; i < expandedKeys.length; i++) {
    if (expandedKeys[i] === data.id) {
      expandedKeys.splice(i, 1);
    }
    let children = data.children;
    if (children && children.length > 0) {
      for (let h = 0; h < children.length; h++) {
        menuNodeCollapseEvent(children[h]);
      }
    }
  }
};

// 过滤菜单
const filterTreeNode = (value, data) => {
  if (!value) {
    return true;
  }
  return data.name.indexOf(value) !== -1;
};

// 表格数据刷新
const loadTableData = () => {
  dataTableRef.value.loadTableData();
};
</script>

<style lang="scss">
.mod-resource {

  .r-title {
    font-size: 16px;
    font-weight: 600;
  }
  
  .toolbar-box {
    margin: 10px 0;
  }

  .el-tree-node__label {
    width: 100%;
  }
}
</style>